package logic

import (
	"context"
	"time"

	"lottery-zero/internal/model"
	"lottery-zero/internal/svc"
	"lottery-zero/internal/types"

	"github.com/dgrijalva/jwt-go"
	"github.com/tal-tech/go-zero/core/logx"
	"golang.org/x/crypto/bcrypt"
)

type LoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) LoginLogic {
	return LoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *LoginLogic) Login(req types.LoginReq) (*types.LoginReply, error) {
	user := model.UserAuth{}
	result := l.svcCtx.PGDB.Where(&model.UserAuth{Name: req.Username}).First(&user)
	if result.RowsAffected == 0 {
		return nil, errorUsernameUnRegister
	}

	// 密码验证
	err := bcrypt.CompareHashAndPassword([]byte(user.Passwrod), []byte(req.Password)) //验证（对比）
	if err != nil {
		return nil, errorIncorrectPassword
	}
	// 发放 token
	now := time.Now().Unix()
	accessExpire := l.svcCtx.Config.Auth.AccessExpire
	jwtToken, err := l.getJwtToken(l.svcCtx.Config.Auth.AccessSecret, now, accessExpire, int64(user.ID))
	if err != nil {
		return nil, err
	}
	userinfo := model.UserInfo{}
	l.svcCtx.PGDB.Where(&model.UserInfo{ID: user.ID}).First(&userinfo)

	return &types.LoginReply{
		UserInfoReply: types.UserInfoReply{
			Id:           user.ID,
			Username:     user.Name,
			Email:        userinfo.Email,
			Nickname:     userinfo.Nickname,
			DingWebHook:  userinfo.DingWebHook,
			Avatar:       userinfo.Avatar,
			Introduction: userinfo.Introduction,
		},
		JwtToken: types.JwtToken{
			AccessToken:  jwtToken,
			AccessExpire: now + accessExpire,
			RefreshAfter: now + accessExpire/2,
		},
	}, nil
}

func (l *LoginLogic) getJwtToken(secretKey string, iat, seconds, userId int64) (string, error) {
	claims := make(jwt.MapClaims)
	claims["exp"] = iat + seconds
	claims["iat"] = iat
	claims["userId"] = userId
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims = claims
	return token.SignedString([]byte(secretKey))
}
